package nio;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class NIOReceiver {
	private static final int BUF_SIZE = 256 * 1024 - 1;
	private static final int FILE_SIZE = 104857600;

	public static void main(String[] args) throws IOException {
		ServerSocketChannel ssc = null;
		int totalSize = 0;

		try {
			ssc = ServerSocketChannel.open();
			ssc.socket().bind(new InetSocketAddress(7777));
			ssc.configureBlocking(true);

			while (true) {
				System.out.println("Waiting for a connection.");
				SocketChannel sc = ssc.accept();
				// if sc == null, that means there is no connection yet
				// do something else
				if (sc == null) {
					// pretend to do something useful here
					System.out.println("Waiting for a connection.");
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				} else { // received an incoming connection
					System.out.println("Received an incoming connection from "
							+ sc.socket().getRemoteSocketAddress());

					int size = BUF_SIZE + 1;

					ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE);

					FileOutputStream fileOutputStream = new FileOutputStream(
							new File("data/net_nio_rcv.bin"));
					FileChannel fileChannel = fileOutputStream.getChannel();

					while (size > 0 && totalSize < FILE_SIZE) {
						buf.clear();
						size = sc.read(buf);
						totalSize += size;
						buf.flip();
						if (size > 0) {
							while (buf.hasRemaining()) {
								fileChannel.write(buf);
							}
						}
					}

					System.out.println("TX ack sent.");
					ByteBuffer ackBuf = ByteBuffer.allocate(1);
					ackBuf.clear();
					ackBuf.put((byte) 77);
					ackBuf.flip();
					sc.write(ackBuf);
					sc.close();

					fileChannel.close();

					System.exit(0);
				}
			}
		} catch (IOException e) {
			System.out.println("Ex. Total rcvd: " + totalSize + "b.");
			e.printStackTrace();
		} finally {
			if (ssc != null) {
				try {
					ssc.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
